import { Injectable, BadRequestException } from '@nestjs/common'
import { InjectRepository } from '@nestjs/typeorm'
import { Like, Repository, In, Not, IsNull } from 'typeorm'
import { CreateUserDto } from './dto/create-user.dto'
import { User } from './entities/user.entity'
import { Avatar } from './entities/avatar.entity'
import { Role } from './entities/role.entity'
import { JwtService } from '@nestjs/jwt'
import Crypto from '@/utils/crypto'
import * as path from 'path'
import * as fs from 'fs'
import * as uuid from 'uuid'

@Injectable()
export class UserService {
  constructor(
    @InjectRepository(User) private readonly user: Repository<User>,
    @InjectRepository(Avatar) private readonly avatar: Repository<Avatar>,
    @InjectRepository(Role) private readonly role: Repository<Role>,
    private readonly jwtService: JwtService
  ) {}

  // 注册用户
  async create(createUserDto: CreateUserDto) {
    if (!createUserDto || !createUserDto.username) throw new BadRequestException('用户名不能为空')
    if (!createUserDto || !createUserDto.password) throw new BadRequestException('密码不能为空')

    const hasUser = await this.hasUser({ username: createUserDto.username })
    if (hasUser) return 'User exists'

    const user = new User()
    user._id = uuid.v4()
    user.username = createUserDto.username
    user.password = await Crypto.hashPassword(createUserDto.password)
    user.state = 1
    user.role_id = 301

    const defaultAvatarPath = path.join(__dirname, '../images/cat.jpg')
    const avatarBuffer = fs.readFileSync(defaultAvatarPath)
    const avatar = new Avatar()
    avatar.user_id = user._id
    avatar.avatar = avatarBuffer
    avatar.contentType = 'image/jpeg'

    // 使用 QueryRunner 来处理事务
    const queryRunner = this.user.manager.connection.createQueryRunner()
    // 开始事务
    await queryRunner.startTransaction()

    try {
      // 保存用户
      await queryRunner.manager.save(User, user)
      // 保存头像
      await queryRunner.manager.save(Avatar, avatar)
      // 提交事务
      await queryRunner.commitTransaction()
      return { data: '', message: '注册成功!' }
    } catch (error) {
      // 回滚事务
      await queryRunner.rollbackTransaction()
      throw new BadRequestException(error.message)
    } finally {
      // 释放 QueryRunner
      await queryRunner.release()
    }
  }

  // 用户登录
  async login(createUserDto: CreateUserDto) {
    if (!createUserDto || !createUserDto.username) throw new BadRequestException('用户名不能为空')
    if (!createUserDto || !createUserDto.password) throw new BadRequestException('密码不能为空')

    try {
      const user = await this.user.findOne({
        where: { username: createUserDto.username }
      })
      if (!user) return { data: '', message: 'User not registered' }
      if (!user.state) return { data: '', message: 'Disabled user' }
      const isAuthenticated = await Crypto.comparePassword(createUserDto.password, user.password)
      if (isAuthenticated) {
        delete user.password
        delete user.state
        const payload = { username: user.username, sub: user._id }
        const accessToken = await this.jwtService.sign(payload)
        return { data: { ...user, token: accessToken }, message: '登录成功!' }
      } else {
        return { data: '', message: 'Password error' }
      }
    } catch (error) {
      throw new BadRequestException(error.message)
    }
  }

  // 修改用户密码
  async changePassword(uid: string, password: string) {
    const user = await this.user.findOneBy({ _id: uid })
    if (!user) throw new BadRequestException('用户不存在')
    try {
      user.password = await Crypto.hashPassword(password)
      await this.user.save(user)
      return { data: { userID: uid }, message: '修改密码成功' }
    } catch (error) {
      throw new BadRequestException(error.message)
    }
  }

  // 修改用户状态
  async changeState(uid: string, state: number) {
    const user = await this.user.findOneBy({ _id: uid })
    if (!user) throw new BadRequestException('用户不存在')
    try {
      user.state = state
      await this.user.save(user)
      return { data: { userID: uid }, message: '修改状态成功' }
    } catch (error) {
      throw new BadRequestException(error.message)
    }
  }

  // 根据 ID 查询用户信息
  async findOne(uid: string) {
    const user = await this.user.findOneBy({ _id: uid })
    if (!user) throw new BadRequestException('用户不存在')
    delete user.password
    return user
  }

  // 根据 ID 删除用户
  async deleteUser(uid: string) {
    const hasUser = await this.hasUser({ _id: uid })
    if (!hasUser) throw new BadRequestException('用户不存在')

    const queryRunner = this.avatar.manager.connection.createQueryRunner()
    await queryRunner.startTransaction()

    try {
      await queryRunner.manager.delete(Avatar, { user_id: uid })
      await queryRunner.manager.delete(User, { _id: uid })
      await queryRunner.commitTransaction()
      return { data: { userID: uid }, message: '删除用户成功' }
    } catch (error) {
      // 回滚事务
      await queryRunner.rollbackTransaction()
      throw new BadRequestException(error.message)
    } finally {
      await queryRunner.release()
    }
  }

  // 修改用户角色
  async changeRole(uid: string, rid: number) {
    const user = await this.user.findOneBy({ _id: uid })
    if (!user) throw new BadRequestException('用户不存在')
    try {
      user.role_id = rid
      await this.user.save(user)
      return { data: { userID: uid }, message: '修改角色成功' }
    } catch (error) {
      throw new BadRequestException(error.message)
    }
  }

  // 分页查询
  async findUser(page: number, limit: number) {
    try {
      const data = await this.user.find({
        order: { createTime: 'ASC' },
        skip: (page - 1) * limit,
        take: limit
      })
      const total = await this.user.count()
      const itemData = await Promise.all(
        data.map(async (user) => {
          const roleInfo = await this.role.findOneBy({ role_id: user.role_id })
          delete user.password
          return {
            ...user,
            avatarPath: `/avatar/${user._id}`,
            role_name: roleInfo.role_name
          }
        })
      )
      return {
        data: {
          isPagination: true,
          itemData,
          total: total,
          page: page,
          totalPage: Math.ceil(total / limit)
        },
        message: '获取用户列表成功'
      }
    } catch (error) {
      throw new BadRequestException(error.message)
    }
  }

  // 模糊查询用户
  async searchUser(username?: string, role_name?: string) {
    const queryInfo: { username: string; role_id: number[] } = {
      username: '',
      role_id: []
    }

    try {
      if (username) queryInfo.username = username
      if (role_name) {
        const roleData = await this.role.find({
          where: {
            role_name: Like(`%${role_name}%`)
          }
        })
        if (roleData && roleData.length > 0) queryInfo.role_id = roleData.map((role) => role.role_id)
      }

      const data = await this.user.find({
        where: {
          username: Like(`%${queryInfo.username}%`),
          role_id: queryInfo.role_id.length > 0 ? In(queryInfo.role_id) : Not(IsNull())
        }
      })
      const itemData = await Promise.all(
        data.map(async (user) => {
          const roleInfo = await this.role.findOneBy({ role_id: user.role_id })
          delete user.password
          return {
            ...user,
            avatarPath: `/avatar/${user._id}`,
            role_name: roleInfo.role_name
          }
        })
      )
      return {
        data: {
          isPagination: false,
          itemData
        },
        message: '获取用户列表成功'
      }
    } catch (error) {
      throw new BadRequestException(error.message)
    }
  }

  private async hasUser({ _id, username }: { _id?: string; username?: string }): Promise<boolean> {
    if (username) {
      const hasUserByName = await this.user.findOneBy({ username })
      if (hasUserByName) return true
    }
    if (_id) {
      const hasUserByID = await this.user.findOneBy({ _id })
      if (hasUserByID) return true
    }
    return false
  }
}
